package com.app.system.config.aspect;

import com.app.log.annotation.MyLog;
import com.app.log.model.LogSystem;
import com.app.log.service.LogSystemService;
import com.app.system.config.properties.SystemParamProperties;
import com.app.system.log4j2.LogUtils;
import com.app.system.utils.ParamUtils;
import com.app.system.utils.WebUtils;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Enumeration;

/**
 * Created by wcf-pc on 2018/5/6.
 */
@Aspect
@Component
@SuppressWarnings("all")
public class SystemLogAspect {

    @Resource
    private SystemParamProperties systemParamProperties;
    @Resource
    private LogSystemService logSystemService;

    private Logger logger = LogUtils.getPlatformLogger();//系统权限日志

    @Pointcut(value = "execution(* com.app.system.permission.web.permission.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        String classMethod = signature.getDeclaringTypeName() + "." + signature.getName();

        Object username = SecurityUtils.getSubject().getPrincipal();//用户名
        String url = request.getRequestURL().toString();
        String uri = request.getQueryString();
        String ip = WebUtils.getIpAddr(request);
        String requestMethod = request.getMethod();
        String out = ip + " | " + username + " | " + classMethod + " | " + url + "?" + uri + " | " + requestMethod;
        logger.info(out);
        if (systemParamProperties.getIsLogForSystem()) {//数据库日志记录开
            MyLog myLog = method.getAnnotation(MyLog.class);//带有@MyLog注解的方法
            if (myLog != null) {
                LogSystem log = new LogSystem();
                Date date = new Date();
                String value = myLog.value();
                log.setOperation(value);//保存获取的操作
                log.setClassMethod(classMethod);
                log.setUrl(request.getRequestURI());
                Enumeration info = request.getParameterNames();
                StringBuffer param = new StringBuffer("");
                String myUri = null;
                while (info.hasMoreElements()) {
                    myUri = (String) info.nextElement();
                    param.append(myUri);
                    param.append("=");
                    param.append(ParamUtils.getString(request, myUri, ""));
                    param.append("&");
                }
                log.setUri(param.toString());
                log.setCreateDate(date);
                log.setCreateDateLong(date.getTime());
                log.setUsername(WebUtils.getLoginUserName());
                log.setIp(ip);
                this.logSystemService.addLogSystem(log);
            }
        }
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求，返回内容
        logger.info("RESPONSE : " + ret);
    }

//    @Around("webLog()")
//    public void around(ProceedingJoinPoint pjp) throws Throwable{
//        this.printLog("已经记录下操作日志@Around 方法执行前");
//        pjp.proceed();
//        this.printLog("已经记录下操作日志@Around 方法执行后");
//    }
}
